%%%-----------------------------------------------------------------------------
%%% @doc
%%% apn_server connect pool
%%%
%%% @end
%%%-----------------------------------------------------------------------------
-module (apn_server_connect_pool).

-behaviour(gen_server).

-define(SERVER, ?MODULE).

%% API Exports 
-export([start_link/1, pool/0, table/0, register/2, lookup/1, unregister/1]).

%% gen_server Function Exports
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).

-record(state, {id}).

-define(APNS_POOL, apns_pool).
-define(APNS_TAB, apns_table).

%%%=============================================================================
%%% API
%%%=============================================================================

%%------------------------------------------------------------------------------
%% @doc Start Ack manager
%% @end
%%------------------------------------------------------------------------------
start_link(Id) ->
    gen_server:start_link(?MODULE, [Id], []).

pool()  -> ?APNS_POOL.

table() -> ?APNS_TAB.

lookup(AppKey) ->
    case ets:lookup(?APNS_TAB, AppKey) of
        [] -> undefined;
        [{_, Pid}]  -> 
            Pid
    end.
    
register(AppKey, Pid) ->
    CmPid = gproc_pool:pick_worker(?APNS_POOL, AppKey),
    gen_server:call(CmPid, {register, AppKey, Pid}, infinity).

unregister(AppKey) ->
    CmPid = gproc_pool:pick_worker(?APNS_POOL, AppKey),
    gen_server:call(CmPid, {unregister, AppKey}, infinity).      


init([Id]) ->
    gproc_pool:connect_worker(?APNS_POOL, {?MODULE, Id}),
    {ok, #state{id = Id}}.

handle_call({register, AppKey, Pid}, _From, State) ->
    ets:insert(?APNS_TAB, {AppKey, Pid}),
    {reply, ok, State};

handle_call({unregister, AppKey}, _From, State) ->
    ets:delete(?APNS_TAB, AppKey),
    {reply, ok, State};    

handle_call(Req, _From, State) ->
    lager:error("unexpected request: ~p", [Req]),
    {reply, {error, badreq}, State}.


handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, #state{id = Id}) ->
    gproc_pool:disconnect_worker(?APNS_POOL, {?MODULE, Id}), 
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.